package cn.tannn.tconfig.client.config;

import cn.tannn.tconfig.client.repository.TRepositoryChangeListener;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.context.environment.EnvironmentChangeEvent;
import org.springframework.context.ApplicationContext;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 数据源 获取/监听修改 接口实现 （在接口里偷懒了 TConfigService#getDefault)
 * @author <a href="https://tannn.cn/">tnnn</a>
 * @version V1.0
 * @date 2024/5/2 下午8:49
 */
@Slf4j
public class TConfigServiceImpl implements TConfigService, TRepositoryChangeListener {

    Map<String,String> config;

    final ApplicationContext applicationContext;

    public TConfigServiceImpl(Map<String, String> config, ApplicationContext applicationContext) {
        this.config = config;
        this.applicationContext = applicationContext;
    }

    @Override
    public String[] getPropertyNames() {
        return this.config.keySet().toArray(new String[0]);
    }

    @Override
    public String getProperty(String name) {
        return config.get(name);
    }

    @Override
    public void onChange(ChangeEvent event) {
        Set<String> keys =  calcChangedKeys(this.config, event.config());
        if(keys.isEmpty()){
            log.info("[tconfig] calcChangedKeys return empty, ignore update.");
            return;
        }
        this.config = event.config();
        if(!config.isEmpty()){
            // 发送 EnvironmentChangeEvent 事件让spring刷新 environment
            log.debug("[tconfig] fire an EnvironmentChangeEvent with keys:" + config.keySet());
            applicationContext.publishEvent(new EnvironmentChangeEvent(config.keySet()));
        }
    }


    /**
     * 计算改变了值的
     * @param oldConfigs 旧集合
     * @param newConfigs 新集合
     * @return 变化了的集合
     */
    private Set<String> calcChangedKeys(Map<String, String> oldConfigs, Map<String, String> newConfigs) {
        // 任何一个为空都是变化了的
        if(oldConfigs.isEmpty()){
            return newConfigs.keySet();
        }
        if(newConfigs.isEmpty()){
            return oldConfigs.keySet();
        }
        // 以新集合为准拿到的变动的key
        Set<String> news = newConfigs.keySet().stream().filter(key -> !newConfigs.get(key).equals(oldConfigs.get(key)))
                .collect(Collectors.toSet());
        // 拿到旧集合里没有的key(新增的
        oldConfigs.keySet().stream().filter(key -> !newConfigs.containsKey(key)).forEach(news::add);
        return news;
    }
}
